package com.junmeng.generic;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class JGenericUtil {

    /**
     * 获得指定类对象的父类的指定位置的泛型的实际类型
     * 注意无法获得传递的泛型，比如直接子类也是泛型，则无法获得子类传递的泛型
     *
     * @param subCls       直接子类
     * @param genericIndex 泛型位置
     * @return 可为null
     */
    public static Type getSuperclassGenericType(Class subCls, int genericIndex) {
        Type type = subCls.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type[] types = parameterizedType.getActualTypeArguments();
            if (types != null && types.length != 0 && genericIndex < types.length && genericIndex >= 0) {
                return types[genericIndex];
            }
        }
        return null;
    }

    /**
     * 获得指定类对象的目标父类的指定位置的泛型的实际类型
     * 注意无法获得传递的泛型
     *
     * @param childCls     子类(可以为非直接子类)
     * @param targetCls    目标父类
     * @param genericIndex 泛型位置
     * @return
     */
    public static Type getSuperclassGenericType(Class childCls, Class targetCls, int genericIndex) {
        Type type = childCls.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            if (parameterizedType.getRawType() == targetCls) {
                Type[] types = parameterizedType.getActualTypeArguments();
                if (types != null && types.length != 0 && genericIndex < types.length && genericIndex >= 0) {
                    return types[genericIndex];
                }
            }
        }
        if (childCls.getSuperclass() == Object.class) {
            return null;
        }
        return getSuperclassGenericType(childCls.getSuperclass(), targetCls, genericIndex);
    }

    /**
     * 获得接口实现类的指定接口的指定位置的泛型
     * 注意无法获得传递的泛型
     *
     * @param interfaceImpl 可以是interfaceRaw的具体实现类或匿名类
     * @param interfaceRaw  指定接口类
     * @param genericIndex  指定泛型位置
     * @return 可为null
     */
    public static Type getInterfaceGenericType(Class interfaceImpl, Class interfaceRaw, int genericIndex) {
        //先直接检查自身的接口是否符合要求
        Type[] types = interfaceImpl.getGenericInterfaces();
        if (types != null && types.length > 0) {
            for (int i = 0; i < types.length; i++) {
                Type it = types[i];
                if (it instanceof ParameterizedType) {
                    ParameterizedType parameterized = (ParameterizedType) it;
                    if (parameterized.getRawType() == interfaceRaw) {
                        Type[] args = parameterized.getActualTypeArguments();
                        if (args != null && args.length != 0 && genericIndex < args.length && genericIndex >= 0) {
                            return args[genericIndex];
                        }
                    }
                }
            }
        }
        //再检查其继承的接口是否符合要求
        for (Class anInterface : interfaceImpl.getInterfaces()) {
            return getInterfaceGenericType(anInterface, interfaceRaw, genericIndex);
        }
        //退出嵌套的条件
        if (interfaceImpl.getSuperclass() == Object.class || interfaceImpl.getSuperclass() == null) {
            return null;
        }

        return getInterfaceGenericType(interfaceImpl.getSuperclass(), interfaceRaw, genericIndex);
    }
}